#ifndef _D9A9C542_DE18_4027_B7E1_F82D839FD8ED
#define _D9A9C542_DE18_4027_B7E1_F82D839FD8ED

#include "depends/incfile.h"
#include "CFunc.h"

namespace x2lib
{
	/*************************************************************************
	** Name		: StrUtil
	** Desc		: 字符串处理函数
	** Author	: xktesla@2016-8-16 22:57:47
	*************************************************************************/
	class StrUtil
	{
	public:
		static char *ToLower(char *str, char *buff = nullptr);
		static char *ToUpper(char *str, char *buff = nullptr);
		static int Compare(const char *str1, const char *str2, bool bIgnoreCase);
		static int IP2Int(const char *strIP);
		static char *IP2Str(int iIP, char *strIP);
		static char *IP2Str(struct sockaddr_in addr, char *strIP);
		// 由于编译成lib时导不出wchar_t型，所以此处使用char代替wcahr_t，真正使用时需要强转为wchar_t
		//static char/*wchar_t*/ *AStr2WStr(char const *str, char/*wchar_t*/ *buff, int len);
		// 由于编译成lib时导不出wchar_t型，所以此处使用char代替wcahr_t，真正使用时需要强转为wchar_t
		//static char *WStr2AStr(char/*wchar_t*/ const *wstr, char *buff, int len);

		static wchar_t *Ansi2Unicode(wchar_t *buff, char const *str, int len);
		static char *Unicode2Ansi(char *buff, wchar_t const *wstr, int len);
		static wchar_t *Utf82Unicode(wchar_t *buff, char const *str, int len);
		static char *Unicode2Utf8(char *buff, wchar_t const *wstr, int len);
		static char *Utf82Ansi(char *buff, char const *str, int len);
		static char *Ansi2Utf8(char *buff, char const *str, int len);
		static char *Gbk2Utf8(char *buff, char const *str, int len);
		static char *Utf82Gbk(char *buff, char const *wstr, int len);

		static std::wstring Ansi2Unicode(const char *str)
		{
			int len = StrLenX((void*)str, 1) * 4 + 8;
            if (len < 1) return L"";

			wchar_t *pTemp = (wchar_t*)malloc(len);
			memset(pTemp, 0, len);
			std::wstring wstr = StrUtil::Ansi2Unicode(pTemp, str, len);
			free(pTemp);
			return wstr;
		};

		static std::string Unicode2Ansi(const wchar_t *wstr)
		{
			int len = StrLenX((void*)wstr, sizeof(wchar_t)) * 2 + 8;
            if (len < 1) return "";

			char *pTemp = (char*)malloc(len);
			memset(pTemp, 0, len);
			std::string str = StrUtil::Unicode2Ansi(pTemp, wstr,len);
			free(pTemp);
			return str;
		};

		static std::wstring Utf82Unicode(const char* str)
		{
			int len = StrLenX((void*)str, 1) * 4 + 8;
            if (len < 1) return L"";

			wchar_t *pTemp = (wchar_t*)malloc(len);
			memset(pTemp, 0, len);
			std::wstring wstr = StrUtil::Utf82Unicode(pTemp, str, len);
			free(pTemp);
			return wstr;
		}

		static std::string Unicode2Utf8(const wchar_t* wstr)
		{
			int len = StrLenX((void*)wstr, sizeof(wchar_t)) * 2 + 8;
            if (len < 1) return "";

			char *pTemp = (char*)malloc(len);
			memset(pTemp, 0, len);
			std::string str = StrUtil::Unicode2Utf8(pTemp, wstr, len);
			free(pTemp);
			return str;
		}

		static std::string Utf82Ansi(const char* str)
		{
			return StrUtil::Unicode2Ansi(StrUtil::Utf82Unicode(str).c_str());
		}

		static std::string Ansi2Utf8(const char* str)
		{
			return StrUtil::Unicode2Utf8(StrUtil::Ansi2Unicode(str).c_str());
		}
		
		static std::string Gbk2Utf8(const char* str)
		{
			int len = StrLenX((void*)str, 1) * 4 + 8;
            if (len < 1) return "";

			char *pTemp = (char*)malloc(len);
			memset(pTemp, 0, len);
			std::string utf8Str = StrUtil::Gbk2Utf8(pTemp, str, len);
			free(pTemp);
			return utf8Str;
		}

		static std::string Utf82Gbk(const char* str)
		{
			int len = StrLenX((void*)str, 1) * 4 + 8;
            if (len < 1) return "";

			char *pTemp = (char*)malloc(len);
			memset(pTemp, 0, len);
			std::string gbkStr = StrUtil::Utf82Gbk(pTemp, str, len);
			free(pTemp);
			return gbkStr;
		}

		static char *Float2Str(float f, char buf[], int len, const char *fmt = nullptr);
		static char *Int2Str(int i, char buf[], int len, const char *fmt = nullptr);

		static std::string Float2Str(float f, const char *fmt = nullptr)
		{
			char szTemp[256] = {0};
			return Float2Str(f, szTemp, sizeof(szTemp), fmt);
		}
		static std::string Int2Str(int i, const char *fmt = nullptr)
		{
			char szTemp[256] = { 0 };
			return Int2Str(i, szTemp, sizeof(szTemp), fmt);
		}

		static int Str2Int(const char *iStr);
		static float Str2Float(const char *fStr);

		static int CalcHash(const char *pStr, bool isUnicode, bool isIgnoreCase);
		// 返回二进制字节数
		static int HexChars2Bytes(const char szChars[], char *pBytes, int nBytes);
		// 返回字符个数，szChars保存的是小写字符串
		static int Bytes2HexChars(char *pBytes, int nBytes, char szChars[], int nChars, char chSep = 0x00);

		/**
		* @brief        分割字符串，并将其保存到pStrs。使用方法如下：
		*					int nStrs = Split("1,2,3,4", ",", nullptr);
		*					char** pStrs = (char**)malloc(nStrs); // 或 char pStrs[m][n]; 只要保证m*n>=nStrs即可
		*					nStrs = Split(str, div, pStrs);
		*					free(pStrs);
		* @param[in]    str 欲分割的字符串
		* @param[in]    div 分隔符
		* @param[out]   pStrs 存储子串，若为nullptr则函数返回pStrs所需大小
		* @return		失败返回-1，当pStrs为nullptr返回所需内存大小，否则返回分割后的个数
		* @author       xktesla@2021-12-9
		*/
		static int Split(const char *str, const char *div, char *pStrs[]);

		/**
		* @brief        分割字符串，使用方法如下：
		*					std::vector<std::string> vecFiled;
		*					Split("1,2,3,4", ",", vecFiled);
		* @param[in]    str 欲分割的字符串
		* @param[in]    div 分隔符
		* @param[out]   vecFiled 存储子串
		* @return		失败返回-1，否则返回子串个数
		* @author       xktesla@2021-12-9
		*/
		static int Split(const char* str, const char* div, std::vector<std::string>& vecField);
		static int Split(char* str, const char* div, std::vector<std::string>& vecField);

		static bool IsChineseHead(const char *str);
		static bool MatchWild(const char *szWild, char *szDst, bool isIgnoreCase);
		static inline int matchstar(int c, char *regexp, char *text);
		static inline int matchhere(char *regexp, char *text);
		static char* Replace(const char *in, char *out, unsigned int outlen, const char *src, const char *dst);

        /*************************************************************************
        ** Desc     : 去掉字符串首尾的空格，换行符等空白（空格(SPC)，水平制表符 (TAB)，换行符 (LF)，垂直制表符 (VT)，换页 (FF)，回车 (CR)）
        ** Param    : [in] pStr 
        **          : [in] iPos 0左右，1左，2右
        ** Return   : pStr
        ** Author   : xktesla
        *************************************************************************/
        static char* Trim(char* pStr, uint8_t iPos = 0);
		static std::string& Trim(std::string& str, uint8_t iPos = 0);

		static std::string& Formats(std::string& str, const char* pszFmt, ...);
#if 0
        //static std::unique_ptr<std::string> Format(const char* pszFmt, ...);
#else
		/*************************************************************************
		** Desc     : 好用的格式化字符串“函数”，使用方法：
		**				printf(StrUtil::Format("%,%s", "hello", "world").c_str());
		** Param    : [in] pszFmt
		**          : [in] ...
		** Return   : std::string
		** Author   : xktesla
		*************************************************************************/
		struct Format : std::string
		{
		public:
			Format(const char* pszFmt, ...)
			{
				va_list body;
				va_start(body, pszFmt);
				int nChars = vsnprintf(0, 0, pszFmt, body) + 1;
				this->resize(nChars);
				va_start(body, pszFmt); // gcc平台必须重新初始化body
				vsprintf((char*)this->data(), pszFmt, body);
				va_end(body);
			}

		private:
			Format() = delete;
			Format(const Format&) = delete;
			Format& operator=(const Format&) = delete;

			//operator std::string()
			//{
			//	return this;
			//}
		};
#endif
	};


}

#endif

